﻿/*
 * @author: wizardc
 */

using UnityEngine;

namespace Dou.Controller
{
    /// <summary>
    /// 限制机位的摄像机工具类
    /// </summary>
    public static class RestrictCameraUtil
    {
        private static readonly RaycastHit[] _raycastResult = new RaycastHit[1];
        
        /// <summary>
        /// 通过屏幕坐标点得到对应地面碰撞体的坐标点
        /// </summary>
        public static bool ScreenPointToGroundPoint(Camera camera, float x, float y, float maxDistance, int layerMask, out Vector3 position)
        {
            var ray = camera.ScreenPointToRay(new Vector3(x, y, 0));
            var count = Physics.RaycastNonAlloc(ray, _raycastResult, maxDistance, layerMask);
            if (count > 0)
            {
                position = _raycastResult[0].point;
                position.y = 0; // 忽略掉 y 轴的拖动量
                return true;
            }
            position = default;
            return false;
        }
        
        public static Vector3 CubicLimit(Vector3 pos, Vector3[] limitPos)
        {
            var min = limitPos[0];
            var max = limitPos[1];
            
            // 前
            if (pos.z > max.z)
            {
                pos.z = max.z;
            }
            // 后
            if (pos.z < min.z)
            {
                pos.z = min.z;
            }
            // 上
            if (pos.y > max.y)
            {
                pos.y = max.y;
            }
            // 下
            if (pos.y < min.y)
            {
                pos.y = min.y;
            }
            // 左
            if (pos.x < min.x)
            {
                pos.x = min.x;
            }
            // 右
            if (pos.x > max.x)
            {
                pos.x = max.x;
            }
            
            return pos;
        }

        public static Vector3 TrapezoidLimit(Vector3 pos, Vector3[] limitPos, float minHeight, float maxHeight)
        {
            var underTopLeft = limitPos[0];
            var underTopRight = limitPos[1];
            var underBottomLeft = limitPos[2];
            var underBottomRight = limitPos[3];
            var aboveTopLeft = limitPos[4];
            var aboveTopRight = limitPos[5];
            var aboveBottomLeft = limitPos[6];
            var aboveBottomRight = limitPos[7];
            
            // 前
            if (pos.z > underTopLeft.z)
            {
                pos.z = underTopLeft.z;
            }
            // 后
            if (pos.z < underBottomLeft.z)
            {
                pos.z = underBottomLeft.z;
            }
            // 上
            if (pos.y > aboveTopLeft.y)
            {
                pos.y = aboveTopLeft.y;
            }
            // 下
            if (pos.y < underTopLeft.y)
            {
                pos.y = underTopLeft.y;
            }
            
            // 根据 z 和 y 计算出左右两边的边界用于判断
            var heightRatio = (pos.y - minHeight) / (maxHeight - minHeight);
            
            var underLeftRatio = (pos.z - underBottomLeft.z) / (underTopLeft.z - underBottomLeft.z);
            var underLeftLimitX = (underTopLeft.x - underBottomLeft.x) * underLeftRatio + underBottomLeft.x;
            var aboveLeftRatio = (pos.z - aboveBottomLeft.z) / (aboveTopLeft.z - aboveBottomLeft.z);
            var aboveLeftLimitX = (aboveTopLeft.x - aboveBottomLeft.x) * aboveLeftRatio + aboveBottomLeft.x;
            var leftLimitX = (aboveLeftLimitX - underLeftLimitX) * heightRatio + underLeftLimitX;
            
            var underRightRatio = (pos.z - underBottomRight.z) / (underTopRight.z - underBottomRight.z);
            var underRightLimitX = (underTopRight.x - underBottomRight.x) * underRightRatio + underBottomRight.x;
            var aboveRightRatio = (pos.z - aboveBottomRight.z) / (aboveTopRight.z - aboveBottomRight.z);
            var aboveRightLimitX = (aboveTopRight.x - aboveBottomRight.x) * aboveRightRatio + aboveBottomRight.x;
            var rightLimitX = (aboveRightLimitX - underRightLimitX) * heightRatio + underRightLimitX;
            
            // 左
            if (pos.x < leftLimitX)
            {
                pos.x = leftLimitX;
            }
            // 右
            if (pos.x > rightLimitX)
            {
                pos.x = rightLimitX;
            }
            
            return pos;
        }
    }
}
